home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1995…tember: Reference Library / Dev.CD Sep 95 RL / Dev.CD Sep 95 RL.toast / mac / Technical Documentation / develop / develop Issue 6 code / TCP / NewsWatcher / NW Source / Source / olddrag.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-05  |  13.7 KB  |  550 lines  |  [TEXT/MMCC]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     olddrag.c
  4.  
  5.     This module handles drag and drop when the Drag Manager is not
  6.     available.
  7.     
  8.     Copyright © 1994-1995, Northwestern University.
  9.  
  10. ----------------------------------------------------------------------------*/
  11.  
  12. #include <stdio.h>
  13.  
  14. #include "glob.h"
  15. #include "olddrag.h"
  16. #include "subscribe.h"
  17. #include "listutil.h"
  18. #include "windutil.h"
  19.  
  20.  
  21.  
  22. static Boolean gFirstCall;        /* true if first click loop call after mouse down */
  23. static ListHandle gSubjectList;    /* handle to subject list record if in extracting
  24.                                    binaries manually dialog, else nil */
  25. static OSErr gErr;                /* error code */
  26.  
  27.  
  28.  
  29. /*----------------------------------------------------------------------------
  30.     DrawDragLine
  31.     
  32.     Draw or erase a horizontal dividing line in a list.
  33.     
  34.     Entry:    list = handle to the list.
  35.             lineV = vertical coordinate in list of line to draw or erase.
  36. ----------------------------------------------------------------------------*/
  37.  
  38. static void DrawDragLine (ListHandle list, short lineV)
  39. {
  40.     GrafPtr port, listPort;
  41.     PenState savePen;
  42.     Rect clipRect;
  43.     static RgnHandle savedClip = nil;
  44.     
  45.     listPort = (**list).port;
  46.  
  47.     GetPort(&port);
  48.     GetPenState(&savePen);
  49.     SetPort(listPort);
  50.     if (savedClip == nil) savedClip = NewRgn();
  51.     GetClip(savedClip);
  52.     
  53.     clipRect = (**list).rView;
  54.     ClipRect(&clipRect);
  55.     PenMode(patXor);
  56.     PenPat(&qd.black);
  57.     PenSize(3, 3);
  58.     MoveTo((**list).rView.left, lineV);
  59.     LineTo((**list).rView.right - 3, lineV);
  60.     
  61.     SetClip(savedClip);
  62.     SetPenState(&savePen);
  63.     SetPort(port);
  64. }
  65.  
  66.  
  67.  
  68. /*----------------------------------------------------------------------------
  69.     GetDestRow
  70.     
  71.     Get the destination row in a list given a mouse position. Also determine
  72.     whether or not the list needs to be scrolled.
  73.     
  74.     Entry:    list = handle to list record.
  75.             mousePt = mouse position in local coordinates.
  76.     
  77.     Exit:    *destRow = row number of cell following destination, or 
  78.                 -10 if mouse to left or right of list.
  79.             *lineV = vertical coordinate of dividing line at destination
  80.                 in local coordinates, or -10 if mouse to left or right of list.
  81.             *scrollDelta = delta in cells that list must be scrolled
  82.                 (-1, 0, or +1).
  83. ----------------------------------------------------------------------------*/
  84.  
  85. static void GetDestRow (ListHandle list, Point mousePt, short *destRow,
  86.     short *lineV, short *scrollDelta)
  87. {
  88.     Rect rView, visible, dataBounds;
  89.     Point cellSize;
  90.     
  91.     rView = (**list).rView;
  92.     visible = (**list).visible;
  93.     dataBounds = (**list).dataBounds;
  94.     cellSize = (**list).cellSize;
  95.  
  96.     /* Check to see if the mouse is to the left or right of the list. */
  97.     
  98.     if (mousePt.h < rView.left || mousePt.h > rView.right) {
  99.         *destRow = -10;
  100.         *lineV = -10;
  101.         *scrollDelta = 0;
  102.         return;
  103.     }
  104.  
  105.     /* See if scrolling is necessary. */
  106.     
  107.     if (mousePt.v < rView.top && visible.top > dataBounds.top) {
  108.         *scrollDelta = -1;
  109.     } else if (mousePt.v > rView.bottom && visible.bottom < dataBounds.bottom) {
  110.         *scrollDelta = +1;
  111.     } else {
  112.         *scrollDelta = 0;
  113.     }
  114.  
  115.     /* Compute the destination row. */
  116.     
  117.     *destRow = (mousePt.v - rView.top + (cellSize.v >> 1)) / cellSize.v + visible.top;
  118.     if (*destRow < visible.top) *destRow = visible.top;
  119.     if (*destRow > visible.bottom) *destRow = visible.bottom;
  120.     if (*destRow > dataBounds.bottom) *destRow = dataBounds.bottom;
  121.     
  122.     /* Compute the v coordinate of the dividing line. */
  123.     
  124.     *lineV = cellSize.v * (*destRow - visible.top) + rView.top - 1;
  125.  
  126.     /* Adjust destination row for scrolling. */
  127.     
  128.     *destRow += *scrollDelta;
  129. }
  130.  
  131.  
  132.  
  133. /*----------------------------------------------------------------------------
  134.     TrackListDrag
  135.     
  136.     Track dragging within a list.
  137.     
  138.     Entry:    theList = handle to list record.
  139.     
  140.     Exit:    *destinationRow = row number of cell following destination
  141.                 when mouse button released, or -1 if no destination.
  142. ----------------------------------------------------------------------------*/
  143.  
  144. static void TrackListDrag (ListHandle theList, short *destinationRow)
  145. {
  146.     Boolean lineDrawn = false;
  147.     Point mousePt;
  148.     short destRow, lineV, scrollDelta, prevLineV;
  149.  
  150.     while (StillDown()) {
  151.     
  152.         GetMouse(&mousePt);
  153.         GetDestRow(theList, mousePt, &destRow, &lineV, &scrollDelta);
  154.         
  155.         /* Erase the old dividing line if necessary. */
  156.         
  157.         if (lineDrawn && (lineV != prevLineV || scrollDelta != 0)) {
  158.             DrawDragLine(theList, prevLineV);
  159.             lineDrawn = false;
  160.         }
  161.         
  162.         /* Autoscroll if necessary. */
  163.         
  164.         if (scrollDelta != 0) MyLScroll(scrollDelta, theList);
  165.         
  166.         /* Draw the new dividing line if necessary. */
  167.         
  168.         if (!lineDrawn && destRow >= 0) {
  169.             DrawDragLine(theList, lineV);
  170.             prevLineV = lineV;
  171.             lineDrawn = true;
  172.         }
  173.         
  174.     }
  175.     
  176.     if (lineDrawn) {
  177.         DrawDragLine(theList, lineV);
  178.         *destinationRow = destRow;
  179.     } else {
  180.         *destinationRow = -1;
  181.     }
  182. }
  183.  
  184.  
  185.  
  186. /*----------------------------------------------------------------------------
  187.     DragMoveGroups
  188.     
  189.     This function handles dragging of groups within a user group list.
  190.     
  191.     Entry:    wind = pointer to user group list window.
  192. ----------------------------------------------------------------------------*/
  193.  
  194. static void DragMoveGroups (WindowPtr wind)
  195. {
  196.     TWindow **info;
  197.     ListHandle theList;
  198.     short destRow;
  199.     Boolean changed;
  200.  
  201.     info = (TWindow**)GetWRefCon(wind);
  202.     theList = (**info).theList;
  203.     
  204.     TrackListDrag(theList, &destRow);
  205.     
  206.     if (destRow >= 0) {
  207.         MoveSelectedListCells(theList, destRow, &changed);
  208.         if (changed) (**info).changed = true;
  209.     }
  210. }
  211.  
  212.  
  213.  
  214. /*----------------------------------------------------------------------------
  215.     DragMoveSubjects
  216.     
  217.     This function handles dragging of subjects within a subject list in the
  218.     extract binaries manually dialog.
  219.     
  220.     Entry:    theList = handle to list record.
  221. ----------------------------------------------------------------------------*/
  222.  
  223. static void DragMoveSubjects (ListHandle theList)
  224. {
  225.     short destRow;
  226.     Boolean changed;
  227.     
  228.     TrackListDrag(theList, &destRow);
  229.     
  230.     if (destRow >= 0) MoveSelectedListCells(theList, destRow, &changed);
  231. }
  232.  
  233.  
  234.  
  235. /*----------------------------------------------------------------------------
  236.     MouseIsOverUserGroupList
  237.     
  238.     Check to see if the mouse is over a user group list.
  239.     
  240.     Exit:    function result = true if mouse is over a user group list.
  241.             *thePt = current mouse position in global coords.
  242.             if function result = true:
  243.                 *theWind = pointer to user group list window.
  244.                 *theInfo = handle to group list window info.
  245.                 *theList = handle to group list record.
  246.             if function result = false:
  247.                 *theWind, *theInfo, *theList unchanged.
  248. ----------------------------------------------------------------------------*/
  249.  
  250. static Boolean MouseIsOverUserGroupList (Point *thePt, WindowPtr *theWind,
  251.     TWindow ***theInfo, ListHandle *theList)
  252. {
  253.     WindowPtr wind;
  254.     TWindow **info;
  255.     ListHandle list;
  256.     Rect rView;
  257.     GrafPtr port;
  258.     Point localPt;
  259.     
  260.     GetPort(&port);
  261.     GetMouse(thePt);
  262.     LocalToGlobal(thePt);
  263.     FindWindow(*thePt, &wind);
  264.     if (wind != nil) {
  265.         info = (TWindow**)GetWRefCon(wind);
  266.         if ((**info).kind == kGroup && (**info).groupKind == kUserGroup) {
  267.             list = (**info).theList;
  268.             rView = (**list).rView;
  269.             localPt = *thePt;
  270.             SetPort(wind);
  271.             GlobalToLocal(&localPt);
  272.             if (PtInRect(localPt, &rView)) {
  273.                 *theWind = wind;
  274.                 *theInfo = info;
  275.                 *theList = list;
  276.                 SetPort(port);
  277.                 return true;
  278.             }
  279.         }
  280.     }
  281.     SetPort(port);
  282.     return false;
  283. }
  284.  
  285.  
  286.  
  287. /*----------------------------------------------------------------------------
  288.     DragSubscribeGroups
  289.     
  290.     This function handles dragging of groups from the full group list window
  291.     or new groups list window to a user group list window. 
  292.     
  293.     There are two stages to the drag:
  294.     
  295.     First, a gray region outline of the cells is dragged out of the starting
  296.     window. The user drags this gray region around the screen until the mouse 
  297.     is over a user group list window. At this point the gray region disappears 
  298.     and the first stage ends.
  299.     
  300.     In the second stage, a bold dividing line is tracked at the location where
  301.     the groups will be copied if the mouse button is released, with autoscrolling.
  302.     If the user moves the mouse to some other user group list window, that
  303.     new window becomes the target window.
  304.     
  305.     Entry:    startWind = pointer to starting group list window.
  306.             startPt = initial click location in starting window, in 
  307.                 local coordinates.
  308.                 
  309.     Exit:    function result = error code.
  310. ----------------------------------------------------------------------------*/
  311.  
  312. static OSErr DragSubscribeGroups (WindowPtr startWind, Point startPt)
  313. {
  314.     WindowPtr curWind;
  315.     TWindow **startInfo, **curInfo;
  316.     ListHandle startList, prevList = nil, curList;
  317.     RgnHandle grayRgn;
  318.     Cell curCell;
  319.     Rect cellRect;
  320.     Point tempPt, prevPt, curPt;
  321.     GrafPtr port;
  322.     GrafPort fullPort;
  323.     Boolean rgnDrawn = true, lineDrawn = false;
  324.     short lineV, prevLineV, destRow, scrollDelta;
  325.     OSErr err = noErr;
  326.     
  327.     GetPort(&port);
  328.  
  329.     startInfo = (TWindow**)GetWRefCon(startWind);
  330.     startList = (**startInfo).theList;
  331.     
  332.     /* Start stage 1 - drag a gray region around. */
  333.     
  334.     /* Construct the gray region from the selected cells in the starting window. */
  335.  
  336.     grayRgn = NewRgn();
  337.     OpenRgn();
  338.     SetPt(&curCell,0,0);
  339.     while (LGetSelect(true, &curCell, startList)) {
  340.         LRect(&cellRect, curCell, startList);
  341.         FrameRect(&cellRect);
  342.         curCell.v++;
  343.     }
  344.     CloseRgn(grayRgn);
  345.     
  346.     /* Offset the gray region to the current mouse location. */
  347.     
  348.     GetMouse(&curPt);
  349.     OffsetRgn(grayRgn, curPt.h - startPt.h, curPt.v - startPt.v);
  350.     
  351.     /* Convert the gray region and the current mouse loc to global coords. */
  352.     
  353.     SetPt(&tempPt, 0, 0);
  354.     LocalToGlobal(&tempPt);
  355.     OffsetRgn(grayRgn, tempPt.h, tempPt.v);
  356.     LocalToGlobal(&curPt);
  357.     
  358.     /* Create a full screen GrafPort. */
  359.  
  360.     OpenPort(&fullPort);
  361.     CopyRgn(GetGrayRgn(), fullPort.visRgn);
  362.     fullPort.portRect = (**GetGrayRgn()).rgnBBox;
  363.     PenPat(&qd.gray);
  364.     PenMode(patXor);
  365.  
  366.     /* Draw the initial gray region. */
  367.     
  368.     FrameRgn(grayRgn);
  369.     prevPt = curPt;
  370.     
  371.     /* Drag the gray region around until the mouse is over a user 
  372.        group list window or the mouse is released. */
  373.     
  374.     while (StillDown()) {
  375.     
  376.         /* Break out of the loop if the mouse is over a user group list. */
  377.     
  378.         if (MouseIsOverUserGroupList(&curPt, &curWind, &curInfo, &curList)) break;
  379.         
  380.         /* Erase the old gray region if necessary. */
  381.         
  382.         if (rgnDrawn && !EqualPt(curPt, prevPt)) {
  383.             FrameRgn(grayRgn);
  384.             rgnDrawn = false;
  385.         }
  386.         
  387.         /* Draw the new gray region if necessary. */
  388.         
  389.         if (!rgnDrawn) {
  390.             OffsetRgn(grayRgn, curPt.h - prevPt.h, curPt.v - prevPt.v);
  391.             FrameRgn(grayRgn);
  392.             prevPt = curPt;
  393.             rgnDrawn = true;
  394.         }
  395.                 
  396.     }
  397.  
  398.     if (rgnDrawn) FrameRgn(grayRgn);
  399.     DisposeRgn(grayRgn);
  400.     ClosePort(&fullPort);
  401.     SetPort(port);
  402.     if (!StillDown()) return noErr;
  403.     
  404.     /* Start stage 2 - track the destination dividing line, switching target
  405.        user group list windows as necessary. */
  406.     
  407.     SetPort(curWind);
  408.     
  409.     while (StillDown()) {
  410.     
  411.         /* If the mouse is in some other user group list window, make that window
  412.            the target window. */
  413.     
  414.         prevList = curList;
  415.         if (MouseIsOverUserGroupList(&curPt, &curWind, &curInfo, &curList)) SetPort(curWind);
  416.         GlobalToLocal(&curPt);
  417.  
  418.         /* Get the destination row. */
  419.         
  420.         GetDestRow(curList, curPt, &destRow, &lineV, &scrollDelta);
  421.         
  422.         /* Erase the old dividing line if necessary. */
  423.         
  424.         if (lineDrawn && (curList != prevList || scrollDelta != 0 || lineV != prevLineV)) {
  425.             DrawDragLine(prevList, prevLineV);
  426.             lineDrawn = false;
  427.         }
  428.         
  429.         /* Autoscroll if necessary. */
  430.         
  431.         if (scrollDelta != 0) MyLScroll(scrollDelta, curList);
  432.         
  433.         /* Draw the new dividing line if necessary. */
  434.         
  435.         if (!lineDrawn && destRow >= 0) {
  436.             DrawDragLine(curList, lineV);
  437.             prevLineV = lineV;
  438.             lineDrawn = true;
  439.         }
  440.         
  441.     }
  442.  
  443.     if (lineDrawn) {
  444.         DrawDragLine(prevList, prevLineV);
  445.         err = CopyOrMoveSelectedGroups(startWind, curWind, destRow, true);
  446.         if (err != noErr) goto exit;
  447.     }
  448.     
  449.     SetPort(port);
  450.     return noErr;
  451.     
  452. exit:
  453.  
  454.     SetPort(port);
  455.     return err;
  456. }
  457.  
  458.  
  459.  
  460. /*----------------------------------------------------------------------------
  461.     OldListClickLoop
  462.     
  463.     The click loop routine for lists. It handles dragging 
  464.     groups between and within group list windows, and dragging subjects
  465.     in the extract binaries manually dialog.
  466.     
  467.     Exit:    function result = true if mouse button still down, false
  468.                 if mouse button released.
  469. ----------------------------------------------------------------------------*/
  470.  
  471. Boolean OldListClickLoop (void)
  472. {    
  473.     static Point firstPt;
  474.     WindowPtr wind;
  475.     TWindow **info;
  476.     ListHandle theList;
  477.     Point thePt;
  478.     Rect rect, cellRect;
  479.     Cell cellClicked;
  480.  
  481.     if (gFirstCall) {
  482.         gFirstCall = false;
  483.         GetMouse(&firstPt);
  484.         return true;
  485.     }
  486.  
  487.     if (gSubjectList == nil) {
  488.         wind = MyFrontWindow();
  489.         if (wind == nil) return false;
  490.         info = (TWindow**)GetWRefCon(wind);
  491.         theList = (**info).theList;
  492.     } else {
  493.         theList = gSubjectList;
  494.     }
  495.     
  496.     SetRect(&rect, firstPt.h - 3, firstPt.v - 3, firstPt.h + 3, firstPt.v + 3);
  497.     cellClicked = LLastClick(theList);
  498.     LRect(&cellRect, cellClicked, theList);
  499.     SectRect(&rect, &cellRect, &rect);
  500.     GetMouse(&thePt);
  501.     if (PtInRect(thePt, &rect)) return true;
  502.     
  503.     gDidDrag = true;
  504.     if (gSubjectList != nil) {
  505.         DragMoveSubjects(theList);
  506.     } else if ((**info).groupKind == kUserGroup) {
  507.         DragMoveGroups(wind);
  508.     } else {
  509.         gErr = DragSubscribeGroups(wind, firstPt);
  510.     }
  511.     return false;
  512. }
  513.  
  514.  
  515.  
  516. /*----------------------------------------------------------------------------
  517.     OldBeginListClick
  518.     
  519.     This function must be called just before calling LClick.
  520.     
  521.     Entry:    subjectList = handle to subject list if extracting
  522.                 binaries manually dialog, else nil.
  523.     
  524.     Exit:    gFirstCall = true, to notify our click loop function that this
  525.                 is the first call after a mouse down.
  526. ----------------------------------------------------------------------------*/
  527.  
  528. void OldBeginListClick (ListHandle subjectList)
  529. {
  530.     gFirstCall = true;
  531.     gSubjectList = subjectList;
  532.     gErr = noErr;
  533. }
  534.  
  535.  
  536.  
  537. /*----------------------------------------------------------------------------
  538.     OldEndListClick
  539.     
  540.     This function must be called just after calling LClick to get and 
  541.     check the error code.
  542.     
  543.     Exit:    function result = error code.
  544. ----------------------------------------------------------------------------*/
  545.  
  546. OSErr OldEndListClick (void)
  547. {
  548.     return gErr;
  549. }
  550.